﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using ThreeDContentPipeline;

namespace AssetImporter
{
    // This is the executable that gets called during the content build process to build each asset
    class Program
    {
        static ContentImporterContext _Context;

        static void Main(string[] args)
        {
            try
            {
                string outputDirectory = args[1];
                string sourceAsset = args[2];
                string importer = args[3];
                string arguments = args[4];

                Console.WriteLine();
                Console.WriteLine("-------------------------------------------------------");
                Console.WriteLine("OutputDirectory - '{0}'", outputDirectory);
                Console.WriteLine("SourceAsset - '{0}'", sourceAsset);
                Console.WriteLine("Importer - '{0}'", importer);
                Console.WriteLine("Arguments - '{0}'", arguments);
                Console.WriteLine("-------------------------------------------------------");
                Console.WriteLine();

                LoadAssemblies(args[0].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));

                _Context = new ContentImporterContext(outputDirectory);
                AddTypeWriters();

                IContentImporter importerObj = Activator.CreateInstance(FindType(importer)) as IContentImporter;
                ExternalReference reference = new ExternalReference(sourceAsset);

                Console.WriteLine();
                Console.WriteLine("Importing Asset - '{0}'", sourceAsset);

                importerObj.Arguments = arguments;

                _Context.ImportObject(reference, importerObj);

                Console.WriteLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType().FullName + " : " + ex.Message);
                Console.WriteLine(ex.StackTrace);
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.GetType().FullName + " : " + ex.InnerException.Message);
                    Console.WriteLine(ex.InnerException.StackTrace);
                }
                if (ex is ReflectionTypeLoadException)
                {
                    foreach (Exception lex in (ex as ReflectionTypeLoadException).LoaderExceptions)
                    {
                        Console.WriteLine(lex.GetType().FullName + " : " + lex.Message);
                        Console.WriteLine(lex.StackTrace);
                    }
                }
                Environment.Exit(1);
            }
        }

        static void LoadAssemblies(string[] assemblies)
        {
            foreach (string assembly in assemblies)
            {
                Console.WriteLine("Loading Assembly - '{0}'", assembly);
                Assembly.LoadFrom(Path.GetFullPath(assembly));
            }
        }

        static void AddTypeWriters()
        {
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (!type.IsAbstract)
                    {
                        if (type.GetInterface("IContentTypeWriter") != null)
                        {
                            Type baseType = type.BaseType;
                            IContentTypeWriter typeWriter = Activator.CreateInstance(type) as IContentTypeWriter;

                            _Context.AddContentTypeWriter(baseType.GetGenericArguments()[0], typeWriter);
                        }
                    }
                }
            }
        }

        static Type FindType(string name)
        {
            Type type = null;

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = assembly.GetType(name);
                if (type != null)
                {
                    break;
                }
            }
            return type;
        }
    }
}
